package fem2;

import fem2.jlinalg.COOMatrix;
import fem2.jlinalg.CSCMatrix;
import inf.jlinalg.IMatrix;
import inf.jlinalg.IMatrixReadOnly;
import inf.jlinalg.IVector;
import inf.jlinalg.MatrixFormat;
import inf.text.ArrayFormat;

import java.util.ArrayList;

import math2.MutableDouble;

/**
 * this class support for basic printing for debugging purposes
 * 
 * @author hbui
 * 
 */
public class Debugger {

	public static void watch(String str) {
		System.out.println(str);
	}

	public static void watch(String... str) {
		for (int i = 0; i < str.length; i++) {
			System.out.print(str[i] + " ");
		}
		System.out.println("");
	}

	public static void watch(int i) {
		System.out.println(i);
	}

	public static void watch(double d) {
		System.out.println(d);
	}

	public static void watch(double... d) {
		System.out.println(ArrayFormat.format(d));
	}

	public static void watch(IVector v) {
		System.out.println(MatrixFormat.format(v));
	}

	public static void watch(IMatrix m) {
		if (m instanceof CSCMatrix) {
			CSCMatrix c = (CSCMatrix) m;
			System.out.println("ColPtr: " + ArrayFormat.format(c.columnPointer()));
			System.out.println("RowInd: " + ArrayFormat.format(c.rowIndex()));
			System.out.println("Values: " + ArrayFormat.format(c.values()));
		} else if (m instanceof COOMatrix) {
			COOMatrix c = (COOMatrix) m;
			int[] I = c.getIRow();
			int[] J = c.getJCol();
			double[] v = c.getValues();
			for (int k = 0; k < c.getNonzeros(); k++) {
				System.out.println("(" + I[k] + "," + J[k] + "): " + v[k]);
			}
		} else {
			System.out.println(MatrixFormat.format(m));
		}
	}

	public static void watch(Object o) {
		if (o instanceof IVector) {
			watch((IVector) o);
		} else if (o instanceof IMatrix) {
			watch((IMatrix) o);
		} else if (o instanceof IMatrixReadOnly) {
			System.out.println(MatrixFormat.format((IMatrixReadOnly) o));
		} else if (o instanceof double[]) {
			System.out.println(ArrayFormat.format((double[]) o));
		} else if (o instanceof double[][]) {
			System.out.println(ArrayFormat.format((double[][]) o));
		} else if (o instanceof int[]) {
			System.out.println(ArrayFormat.format((int[]) o));
		} else if (o instanceof Integer) {
			System.out.println(o);
		} else if (o instanceof Double) {
			System.out.println(o);
		} else if (o instanceof MutableDouble) {
			System.out.println(o);
		} else if (o instanceof ArrayList<?>) {
			ArrayList<?> ao = ((ArrayList<?>) o);
			for (int i = 0; i < ao.size(); i++) {
				Debugger.watch(ao.get(i));
			}
		} else {
			throw new Error("class is not supported for printing");
		}
	}

	public static void watch(String str, Object o) {
		System.out.print(str);
		Debugger.watch(o);
	}

	public static void warn(String str) {
		System.out.println("Warning: " + str);
	}

	public static void warn(Object o, String str) {
		System.out.println(o.getClass().getName() + " warning: " + str);
	}

	public static void error(String str) {
		throw new Error(str);
	}
}
